home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FontHandlerMisc.c
-
- Contains: QuickDraw GX to PostScript conversion code.
-
- Version: Technology: Quickdraw GX 1.1.x
-
- Copyright: © 1991-1997 by Apple Computer, Inc., all rights reserved.
- */
-
- #include <GXExceptions.h>
- #include <MacMemory.h>
- #include <Resources.h>
- #include <String.h>
- #include <TextUtils.h>
- #include <Collections.h>
- #include "IOUtilities.h"
- #include "GXToPSBuildConfig.h"
- #include "GXPrintingUniverse.h"
- #include "PSProcSetIDs.h"
- #include "FontDatabase.h"
- #include "FontHandler.h"
- #include "FHResources.h"
- #include "FontHandlerPrivate.h"
- #include "FontHandlerVariations.h"
-
- #define noDEBUGFONTSCANTBEUSED
-
- /***********************************************
-
- Function: FHSetWorkHandleSize
-
- Function sets the size of the work handle to the
- requested size and makes it non-purgeable.
-
- The handle is returned in h.
- passing nil indicates that the routine
- is being called to resize from a previous
- SetWorkHandleSize on the indexed handle
- rather than one that is being used as a new allocation.
- This is primarily for debugging purposes.
-
- index is which handle to grow.
-
- *************************************************/
- OSErr FHSetWorkHandleSize(TFontHandlerHdl hFHRec, long size, long index, Handle *h)
- {
- OSErr status = noErr;
- TFontHandlerPtr pFHRec;
- Handle workHandle;
- long currSize;
-
- pFHRec = *hFHRec;
-
- check(index < kMaxWrkSpaces);
-
- #if DEBUGLEVEL > 0
- if (pFHRec->workHandleInUse[index] && (h != nil)) {
-
- dprintf(notrace, "Fatal Error, Bug!! WorkHandle %d is already in use!!", index);
- return(-999);
-
- } else {
-
- pFHRec->workHandleInUse[index] = true;
-
- }//end if
- #endif
-
- workHandle = pFHRec->workHandle[index];
- HNoPurge(workHandle);
- currSize = pFHRec->workSize[index];
-
- if (*workHandle == 0) { // Was it purged?
-
- ReallocateHandle(workHandle, size);
- status = MemError();
- (*hFHRec)->workSize[index] = size;
-
- } else if (currSize < size) {
-
- status = PrSetHandleSize(workHandle, size);
- (*hFHRec)->workSize[index] = size;
-
- }//end if
-
-
- if (h != nil) {
- *h = workHandle;
- //dprintf(trace, "Allocated handle: %d", index);
- }//end if
-
- return(status);
-
- }//FHSetWorkHandleSize
-
-
-
- /***********************************************
-
- Function: FHReleaseWorkspace
-
- Function marks the workspace purgeable.
- Call when done with a workspace.
-
- index is which handle to grow.
-
- *************************************************/
- void FHReleaseWorkspace(TFontHandlerHdl hFHRec, long index)
- {
- Handle h = (*hFHRec)->workHandle[index];
-
- #if DEBUGLEVEL > 0
- (*hFHRec)->workHandleInUse[index] = false;
- #endif
-
- HUnlock(h);
- HPurge(h);
-
- //dprintf(trace, "released handle: %d", index);
-
- }//FHReleaseWorkspace
-
-
- //<FF>
- /************************************
-
- Function: CountGlyphBits
-
- Function counts the number of glyphs used
- in a font by counting the 1-bits in the
- bit array.
-
- *************************************/
- long CountGlyphBits(unsigned long* glyphBits, long nGlyphs)
- {
- register unsigned long mask = 0x80000000;
- register unsigned long nextLong = *glyphBits;
- long i;
- long count = 0;
-
- for (i = 0; i < nGlyphs; ++i) {
-
- if (nextLong & mask) // check the bit.
- ++count;
-
- /** Advance the mask, and check to see if done a longword. **/
- if ( !(mask >>= 1) ) {
-
- /* If the mask became zero, time to get next longword */
-
- mask = 0x80000000;
- nextLong = *(++glyphBits);
-
- }//end if
-
- }//end for
-
- return(count);
-
- }//CountGlyphBits
-
- //<FF>
- /******************************************
-
- Function: FHGetFontName
-
- This is a wrapper for GXGetFontName. Does exactly
- the same thing and takes the same parameters.
-
- Additionally, it handles the case where the name index
- for a postscript name is zero in which case it fabricates
- one from the font reference instead of returning nothing.
-
- This allows us to print bogus fonts without postscript names.
-
- If the index is zero, then the font name becomes:
- "GXNoPSName-X" where X is the hex version of the font reference.
-
- *******************************************/
- long FHGetFontName(gxFont fontID, long index, gxFontName *name, gxFontPlatform *platform,
- gxFontScript *script, gxFontLanguage *language, unsigned char text[])
- {
- long namelen;
-
- if (index != kNoSuchFontName) {
-
- /* get the real one */
-
- namelen = GXGetFontName(fontID, index, name, platform, script, language, text);
-
- } else {
-
- /* Make up a name */
-
- memcpy(text, "GXNoPSName-", 11);
- HexBlockMove((unsigned char*)&fontID, text + 11, sizeof(gxFont) );
- namelen = 11 + 2 * sizeof(gxFont);
-
- #if DEBUGLEVEL > 1
- {
- unsigned char theName[255];
- long nameSize;
- nameSize = GXFindFontName(fontID, gxUniqueFontName, gxNoPlatform, gxNoScript, gxNoLanguage, theName, nil);
- theName[nameSize] = 0x00;
- dprintf(trace, "font: %s has no valid PostScript name, using: %s", theName, text);
- }
- #endif
-
- }//end if
-
- check(namelen);
-
- return(namelen);
-
- }//FHGetFontName
-
-
-
-
-
-
- //<FF>
- /******************************************
-
- Function: FHGeneratePrinterName
-
- Function generates a printer font name for
- the specified printer font record.
-
- theFont: The font reference.
- printerFont: The printer font record.
- name: pointer to a 256 character string.
- This will be a null terminated string.
-
- returned: The length of the string.
-
- *******************************************/
- long FHGeneratePrinterName(TPrinterFontRec *printerFont, unsigned char name[256])
- {
- long nameLen;
- unsigned char numString[32];
- Boolean addSuffix = false;
- Boolean nameOfComposite = false; // make name for synthetic composite font?
-
- /*****
- Determine whether or not to add suffix before calling GetFontName in case mem moves
- Because the printerFont rec may be inside unlocked handle.
-
- Add the printer font index as a suffix to the name; example Chicago$0$1.
- Only do this if the index is greater than zero or the font is a resident font,
- or the dbIndex of the snapshot font is > 0 or we want name of synthetic composite font.
- (We don't want to give a re-encoding of a resident font the same name as the resident font)
- For index 0, just use the PostScript
- name. This helps apps like FreeHand which depend on the name of the font being the
- PostScript name from the FOND work properly.
-
- dbIndex > 1 forces us to not add a suffix for the first variation snapshot, so that Freehand
- will recognize GX graphics and other variations fonts when printing from QD.
- *****/
-
- if (!(printerFont->info & fontCantBeRencoded))
- if ((printerFont->prFontIndex > 0) || (printerFont->info & fontIsInPrinter) || (printerFont->dbIndex > 1))
- addSuffix = true;
-
- nameLen = FHGetFontName(printerFont->theRealFont, printerFont->nameIndex, nil, nil, nil, nil, name);
-
-
- if (addSuffix) {
-
- /** Add the snapshot index into the name **/
-
- name[nameLen++] = '$';
- NumToString((long)(printerFont->dbIndex), numString);
- memcpy(name + nameLen, &numString[1], numString[0]);
- nameLen += numString[0];
-
-
- /** Add the printer font index to the name **/
-
- name[nameLen++] = '$';
- NumToString(printerFont->prFontIndex, numString);
- memcpy(name + nameLen, &numString[1], numString[0]);
- nameLen += numString[0];
-
- }//end if
-
- /** Add a null byte to end to make it a C friendly string, but don't increment length byte **/
-
- name[nameLen] = 0;
-
- return(nameLen);
-
- }//FHGeneratePrinterName
-
-
-
-
- //<FF>
- /***************************************
-
- Function: FHGetStylePrFontIndex
-
- function returns the printer font index
- associated with a style
-
- ****************************************/
- long FHGetStylePrFontIndex(gxStyle theStyle)
- {
- gxTag fontIndexTag;
- long index;
-
- GXGetStyleTags(theStyle, prFontIndexTag, 1, 1, &fontIndexTag);
- GXGetTag(fontIndexTag, nil, &index);
-
- ncheck(GXGetGraphicsError(nil));
- return(index);
-
- }//FHGetStylePrFontIndex
-
-
- //<FF>
- /**************************************
-
- Wrapper for GXGetStyleFont.
- Makes sure that we never get nil.
-
- ***************************************/
- gxFont FHgxGetStyleFont(gxStyle theStyle)
- {
- gxFont theFont = GXGetStyleFont(theStyle);
- if (theFont == nil)
- theFont = GXGetDefaultFont();
-
- return(theFont);
- }
-
-
-
- //<FF>
- /******************************************
-
- Function: FHFontMayBe2Byte
-
- Function tests to see if a font supports a 2 byte
- script.
-
- *******************************************/
- Boolean FHFontMayBe2Byte(gxFont theFont)
- {
- long encodingCount;
- long i;
- gxFontPlatform thePlatform;
- gxFontScript theScript;
-
- encodingCount = GXCountFontEncodings(theFont);
-
- for (i = 1; i <= encodingCount; ++i) {
-
- thePlatform = GXGetFontEncoding(theFont, i, &theScript, nil);
-
- if ( (theScript == gxJapaneseScript) ||
- (theScript == gxTraditionalChineseScript) ||
- (theScript == gxChineseScript) ||
- (theScript == gxKoreanScript) ) {
-
- return(true);
-
- }//end if
-
- }//end for
-
- return(false);
-
- }//FHFontMayBe2Byte
-
- //<FF>
- /**********************************
-
- Routine tests to see if a font requires
- snapshots or not to do variations given
- the set of legal stream types. We can also
- find out from this call if a font can be
- streamed at all.
-
- We us the variationQueryStreamAction to find
- out both at the same time.
-
- theFont: The font in question
- psDevice: A pointer to a device object.
- legalStreamTypes: The allowable streaming types for the target device.
- productDescription: The product description string.
- requirements: Code indicating stream requirements for the font.
-
- ***********************************/
- OSErr FHGetStreamRequirements(gxFont theFont, CGXtoPostScriptDevice *psDevice, scalerStreamTypeFlag legalStreamTypes,
- char *productDescription, TFHStreamRequirements *requirements)
- {
- OSErr status;
- scalerStream streamRecord;
-
- streamRecord.types = legalStreamTypes;
- streamRecord.targetVersion = productDescription;
- streamRecord.action = variationQueryStreamAction;
- streamRecord.variationCount = selectAllVariations;
- streamRecord.variations = nil;
-
- status = psDevice->StreamFont(theFont, &streamRecord);
-
- if (status == unsupported_font_scaler_stream_format) {
-
- /* This is not an abort case, just note font can't be streamed */
-
- status = noErr;
- *requirements = fhCantStreamFont;
-
- #if DEBUGLEVEL > 0
- dprintf(trace, "Font %X can't be streamed", theFont);
- #endif
-
- } else {
-
- nrequire(status, failed_stream);
-
- /* If there was no error, find out if there is a snapshot requirement */
-
- if (streamRecord.info.variationQueryResult & 0x00000001)
- *requirements = fhNeedsSnapShots;
- else
- *requirements = fhNormalStreaming;
-
- }//end if
-
- failed_stream:
- return(status);
-
- }//FHGetStreamRequirements
-
-
- //<FF>
- /******************************************
-
- Function: FHTestFontCanBeUsed
-
- Function looks at a font and decides whether
- or not the font can be used at all (answer
- no means the font handler client (Imaging Engine for example)
- mush do something other than using the printer font
- (downloaded or resident) to render the glyphs (such as host rasterization).
-
- hFHRec: Font handler context handle.
- theFont: fhFont reference.
- glyphsUsed: Total number of glyphs used by the document
- glyphsEncoded: Total number of glyphs encoded for printer resident font.
-
- ******************************************/
- OSErr FHTestFontCanBeUsed(TFontHandlerHdl hFHRec, fhFont theFont, long glyphsUsed, long glyphsEncoded, Boolean *canUseFont)
- {
- OSErr status = noErr;
- gxFont theRealFont; // the actual gx font reference implied by the fhFont value.
- TFHStreamRequirements requirements; // Stream Requirements for this font.
-
-
- *canUseFont = true;
-
- theRealFont = FHGetSnapShotFont(hFHRec, theFont, nil);
- check(theRealFont);
-
- /* If we need to download any glyphs and it is a Morisawa font, return false - they don't stream */
-
- if ( (glyphsUsed - glyphsEncoded) > 0 ) {
-
- /* Streaming may not be allowed by scaler for this font */
-
- status = FHGetStreamRequirements( theRealFont, (*hFHRec)->psDevice, (*hFHRec)->legalStreamTypes,
- (*hFHRec)->productDescription, &requirements);
-
- nrequire(status, failed_getRequirements);
-
- if ( requirements == fhCantStreamFont ) {
-
- *canUseFont = false;
-
- #if DEBUGLEVEL > 1
- dprintf(trace, "Can't download Font font, Client should do Bitmaps or paths");
- #endif
-
- }//end if
-
- } else if ( (*hFHRec)->printerCanDoAllFonts || ( (glyphsUsed - glyphsEncoded) <= 256) ) {
-
- /** If we need to dowload 256 or fewer glyphs or printer doesn't care, return true **/
-
- #ifdef DEBUGFONTSCANTBEUSED
- char theName[255];
- long nameSize;
- theRealFont = FHGetSnapShotFont(hFHRec, theFont, nil);
- nameSize = GXFindFontName(theRealFont, gxUniqueFontName, gxNoPlatform, gxNoScript, gxNoLanguage, theName, nil);
- theName[nameSize] = 0x00;
- if (glyphsUsed - glyphsEncoded > 0)
- dprintf(trace, "Font %s will be downloaded!, #glyphs required: %d", theName, glyphsUsed - glyphsEncoded);
- else
- dprintf(trace, "Font on printer %s will be used!", theName);
-
- #endif
-
- *canUseFont = true;
-
- } else {
-
- /** If the font is a two byte font and we need to download more than 256 glyphs, set return false **/
-
- if ( FHFontMayBe2Byte(theRealFont) ) {
-
- #ifdef DEBUGFONTSCANTBEUSED
- char theName[255];
- long nameSize;
- nameSize = GXFindFontName(theRealFont, gxUniqueFontName, gxNoPlatform, gxNoScript, gxNoLanguage, theName, nil);
- theName[nameSize] = 0x00;
- dprintf(trace, "Font %s cannot be used!, #glyphs required: %d", theName, glyphsUsed - glyphsEncoded);
- #endif
-
- *canUseFont = false;
-
- }//end if
-
- }//end if
-
- failed_getRequirements:
-
- return(status);
-
- }//FHTestFontCanBeUsed
-
-
-
- /*******************************
-
- Function decides based on product
- name whether or not the printer can
- handle all font downloading. If it can't
- then this implies that shapes with certain
- fonts will cause ResolveShapeFonts to return
- the outline_font_not_found error - implying
- that the client should take other action.
-
- productName: pascal string for product name.
- printerCan: (returned) can the printer handle all downlaoded fonts.
-
- **********************************/
- OSErr FHCanPrinterHandleAllFonts(unsigned char *productName, Boolean *printerCan)
- {
- OSErr status = noErr;
- Handle printerNames;
- unsigned char *name;
- short nameCount, counter;
-
- *printerCan = true;
-
- printerNames = GetResource('STR#', kFHPrintersThatCantDoAllFonts);
- require(printerNames, failed_getnames);
-
- /** Traverse all of the names in the resource, search for match **/
-
- name = (unsigned char*)*printerNames;
- nameCount = *((short*)name);
- name += 2;
-
- for (counter = 0; counter < nameCount; ++counter) {
-
- if (productName[0] == name[0] ) {
-
- if ( memcmp( productName + 1, name + 1, productName[0]) == 0 ) {
-
- #ifdef DEBUGFONTSCANTBEUSED
- dprintf(trace, "Printer can't do all fonts: %s", productName + 1);
- #endif
-
- *printerCan = false;
- break;
-
- }//end if
-
- }//end if
-
- name += name[0] + 1; // point to the next string in the resource.
-
- }//end for
-
-
- return(status);
-
- failed_getnames:
- status = MemError();
- if (status == noErr)
- status = ResError();
-
- return(status);
-
- }//FHCanPrinterHandleAllFonts
-
-
-
-
-
- /***************** Utility routines *******************/
-
-
- /**************************
-
- Function: FHCountPrinterFonts
-
- Returns the number of printer fonts for a document font.
-
- ***************************/
- long FHCountPrinterFonts(TFontHandlerHdl hFHRec, fhFont theFont)
- {
- long nPrFonts;
-
- nPrFonts = CountTaggedCollectionItems((*hFHRec)->printerFontsOffsets, (CollectionTag)theFont);
-
- return(nPrFonts);
-
- }//FHCountPrinterFonts
-
-
-
- /**************************
-
- Function: FHGetIndexedPrinterFont
-
- Returns the Pointer to a printer font record for a document font.
-
- hFHRec: pointer to the font handler context. (Note, returned printer font pointer is only valid if handle does't move)
- theFont: The Document font in question.
- index: Index of the desired printer font.
- printerFont: (returned) pointer to the printer font record.
- theOffset: offset into printer font list so printerFont can be recomputed if handle moves.
-
- ***************************/
- OSErr FHGetIndexedPrinterFont(TFontHandlerHdl hFHRec, fhFont theFont, long index, TPrinterFontRec* *printerFont, long *theOffset)
- {
- OSErr status;
- long offset;
-
- /** For a two byte group member, return the zero'th printer font **/
-
- if (index == kTwoByteGroupIndex)
- index = 0;
-
- *printerFont = nil;
- status = GetCollectionItem((*hFHRec)->printerFontsOffsets,
- (CollectionTag)theFont,
- index,
- nil,
- &offset);
- nrequire(status, failed_GetItem);
-
- *printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);
-
- if (theOffset != nil)
- *theOffset = offset;
-
- failed_GetItem:
-
- return(status);
-
- }//FHGetIndexedPrinterFont
-
-
-
-